/*
 * A simple ToDo Manager
 *
 * Copyright (c) 2011 Nosheen Zaza, Manuel Rebollo, Seyedsaeid Mahpeikar and
 * Wo Ke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package todomanager.ui;


import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.Shape;
import javax.swing.JPanel;

/**
 * A small extension to JPanel, meant to allow
 * the JPanel to support a tiling image background.
 * The tiled background is correctly drawn inside
 * any Border that the panel might have.  Note
 * that JTiledPanel containers are always opaque.
 * If you give the tiling image as null, then
 * JTiledPanel behaves exactly like an opaque
 * JPanel.
 * @author  http://www.javafaq.nu/java-example-code-660.html
 */
public class JTiledPanel extends JPanel {

    private Image tileimage;
    private int tilewidth;
    private int tileheight;
    private Rectangle rb;
    private Insets ri;

    /**
     * Create a JTiledPanel with the given image.
     * The tile argument may be null, you can set it later
     * with setTileImage().  Note that a JTiledPanel is
     * always opaque.
     * @param tile
     */
    public JTiledPanel(Image tile) {
        super();
        setTileImage(tile);
        setOpaque(true);
        rb = new Rectangle(0, 0, 1, 1);
        ri = new Insets(0, 0, 0, 0);
    }

    /**
     * Create a JTiledPanel with the given image and
     * layout manager and double buffering status.
     * Either or both of the first two arguments
     * may be null.
     * @param tile 
     * @param isDB
     * @param mgr
     */
    public JTiledPanel(Image tile, LayoutManager mgr, boolean isDB) {
        super(mgr, isDB);
        setTileImage(tile);
        setOpaque(true);
        rb = new Rectangle(0, 0, 1, 1);
        ri = new Insets(0, 0, 0, 0);
    }

    /**
     * Get the current tiling image, or null if there
     * isn't any right now.
     * @return
     */
    public Image getTileImage() {
        return tileimage;
    }

    /**
     * Set the current tiling image.  To prevent tiling,
     * call this method with null.  Note that this method
     * does NOT call repaint for you; if you want the panel
     * to repaint immediately, you must call repaint()
     * yourself.
     * @param tile
     */
    public void setTileImage(Image tile) {
        tileimage = tile;
        tilewidth = 0;
        tileheight = 0;
    }

    /**
     * Paint this component, including the tiled
     * background image, if any.
     * @param g
     */
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (tileimage != null && tilewidth <= 0) {
            tileheight = tileimage.getHeight(this);
            tilewidth = tileimage.getWidth(this);
        }
        if (tileimage != null && tilewidth > 0) {
            Color bg = getBackground();
            getBounds(rb);
            Insets riv = getInsets(ri);
            rb.translate(riv.left, riv.top);
            rb.x = 0;
            rb.y = 0;
            rb.width -= (riv.left + riv.right);
            rb.height -= (riv.top + riv.bottom);
            Shape ccache = g.getClip();
            g.clipRect(rb.x, rb.y, rb.width, rb.height);
            int xp, yp;
            for (yp = rb.y; yp < rb.y + rb.height; yp += tileheight) {
                for (xp = rb.x; xp < rb.x + rb.width; xp += tilewidth) {
                    g.drawImage(tileimage, xp, yp, bg, this);
                }
            }
            g.setClip(ccache);
        }
    }
}
